package com.yangxk.kadmin.web.common.exception;

import com.yangxk.kadmin.common.beans.Result;
import com.yangxk.kadmin.common.exception.*;
import com.yangxk.kadmin.web.common.enumeration.ResponseCode;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

@RestControllerAdvice
public class ControllerAdvice {

    @ExceptionHandler(Exception.class)
    public Result handler(Exception e, HttpServletResponse response) {
        e.printStackTrace();
        
        /*****************springMVC异常****************************/
        // valid参数校验错误
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400
        if (e instanceof BindException) {
            BindException ex = (BindException) e;
            List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
            return handlerValidError(fieldErrors);
        }
        // valid参数校验错误
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
            return handlerValidError(fieldErrors);
        }

        // 参数错误(类型 缺少)
        if (e instanceof TypeMismatchException
                || e instanceof MissingServletRequestParameterException
                || e instanceof ServletRequestBindingException) {
            return Result.ofError(ResponseCode.ILLEGAL_PARAM);
        }

        // 请求错误
        if (e instanceof HttpMediaTypeNotSupportedException
                || e instanceof HttpMediaTypeNotAcceptableException
                || e instanceof HttpMessageNotReadableException
                || e instanceof HttpMessageNotWritableException
                || e instanceof MissingServletRequestPartException) {
            return Result.ofError(ResponseCode.REQUEST_BAD);
        }

        // 请求方法不支持
        if (e instanceof HttpRequestMethodNotSupportedException) {
            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); // 405
            return Result.ofError(ResponseCode.NOT_SUPPORT_REQUEST_METHOD);
        }

        // 请求地址不存在
        if (e instanceof NoHandlerFoundException) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 404
            return Result.ofError(ResponseCode.NO_REQUEST_URL);
        }

        /***********自定义业务异常****************/
        // 需要登录
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
        if (e instanceof UnLoginException) {
            return Result.ofError(ResponseCode.NEED_LOGIN);
        }

        // 没有权限
        if (e instanceof NoPermissionException) {
            return Result.ofError(ResponseCode.NO_PERMISSION);
        }
        
        // 访问频繁
        if (e instanceof AccessException) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403
            return Result.ofError(ResponseCode.ACCESS_LIMIT);
        }

        // 参数异常
        if (e instanceof ParamException) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400
            return Result.ofError(ResponseCode.ILLEGAL_PARAM.getCode(), e.getMessage());
        }

        // 自定义异常
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500
        if (e instanceof BizException) {
            BizException biz = (BizException)e;
            return Result.ofError(biz.getBaseExceptionEnum());
        }

        // 未知异常
        return Result.ofError();
    }

    private Result handlerValidError(List<FieldError> errors) {
        FieldError fieldError = errors.get(0);
        return Result.ofError(ResponseCode.ILLEGAL_PARAM.getCode(), fieldError.getDefaultMessage());
    }
}
